package com.pxmeta.party.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pxmeta.common.constant.Status;
import com.pxmeta.common.exception.ServiceException;
import com.pxmeta.common.utils.StringUtils;
import com.pxmeta.party.entity.Association;
import com.pxmeta.party.entity.AssociationUser;
import com.pxmeta.party.entity.dto.CreateAssociationDTO;
import com.pxmeta.party.entity.vo.AssociationDetailVO;
import com.pxmeta.party.mapper.AssociationMapper;
import com.pxmeta.party.service.IAssociationService;
import com.pxmeta.party.service.IAssociationUserService;
import com.pxmeta.user.entity.User;
import com.pxmeta.user.mapper.UserMapper;
import com.pxmeta.user.service.IUserBillService;
import com.pxmeta.user.service.IUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class AssociationServiceImpl extends ServiceImpl<AssociationMapper, Association> implements IAssociationService {

    private final UserMapper userMapper;

    @Autowired
    private IUserBillService userBillService;

    @Autowired
    private  IAssociationUserService associationUserService;

    @Override
    public List<Association> getRankingList() {
        LambdaQueryWrapper<Association> wrapper = Wrappers.lambdaQuery();
        wrapper.orderByDesc(Association::getLevel)
                .last("limit 50");
        return this.list(wrapper);
    }

    @Override
    public AssociationDetailVO getAssociationDetail(Long userId, Long associationId) {
        Association association = this.getById(associationId);
        AssociationDetailVO vo = new AssociationDetailVO();
        BeanUtils.copyProperties(association, vo);
        //如果当前用户是该公会的公会长，则展示收益信息。
        if (userId.equals(association.getPresidentUserId())){
            vo.setIsPresident(Boolean.TRUE);
            vo.setIsAdmin(Boolean.TRUE);
            //todo
            IPage<AssociationUser> signingPage = associationUserService.getSigningList(associationId, Status.SUCCESS.getValue(), 1, 1000);
            List<AssociationUser> signingList = signingPage.getRecords();
            signingList.stream().map(AssociationUser::getTotalEarnings).reduce(BigDecimal::add).ifPresent(vo::setTotalEarnings);
            signingList.stream().map(AssociationUser::getWeekEarnings).reduce(BigDecimal::add).ifPresent(vo::setWeekEarnings);
        }

        Long presidentUserId = vo.getPresidentUserId();
        User presidentUser = userMapper.selectById(presidentUserId);
        vo.setPresidentUser(presidentUser);

        if (!vo.getIsPresident()){
            AssociationUser associationUser = associationUserService.getUserSign(userId);
            if (associationUser != null){
                vo.setIsAdmin(associationUser.getIsAdmin());
            }
        }

        Integer applyStatus = getApplyStatus(userId, associationId);
        //如果当前用户是会长，则状态为加入状态
        if(userId.equals(association.getPresidentUserId())){
            applyStatus = Status.SUCCESS.getValue();//已加入
        }
        vo.setApplyStatus(applyStatus);
        return vo;
    }

    //获取用户公会申请状态
    public Integer getApplyStatus(Long userId, Long associationId){
        LambdaQueryWrapper<AssociationUser> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(AssociationUser::getUserId, userId)
                .ne(AssociationUser::getStatus, -1)
                .eq(AssociationUser::getAssociationId, associationId);

        AssociationUser associationUser = associationUserService.getOne(wrapper);

        if (associationUser == null){
            return Status.FAIL.getValue(); //未申请
        }

        return associationUser.getStatus();
    }

    @Override
    public Association getUserAssociation(Long userId) {
        LambdaQueryWrapper<AssociationUser> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(AssociationUser::getUserId, userId)
                .eq(AssociationUser::getStatus, Status.SUCCESS.getValue());
        AssociationUser associationUser = associationUserService.getOne(wrapper);
        if (null == associationUser){
            return null;
        }
        Long associationId = associationUser.getAssociationId();
        return this.getById(associationId);
    }


    /**
     * 解约主播
     * @param userId
     * @param anchorId
     * @param associationId
     */
    @Override
    public void breakAnchor(Long userId, Long anchorId,Long associationId) {
        Association association = this.getById(associationId);

        if (userId.equals(anchorId)){
            throw new ServiceException("不能解约自己！");
        }

        if (!association.getPresidentUserId().equals(userId)){
            throw new ServiceException("您不是公会长，没有权限解约主播！");
        }

        associationUserService.approval(associationId, anchorId, Status.FAIL.getValue());//解约。
    }

    @Override
    public void breakAssociation(Long userId, Long associationId) {
        associationUserService.approval(associationId, userId, Status.FAIL.getValue());//解约。
    }

    @Override
    public void dissolutionAssociation(Long userId) {

        User user = userMapper.selectById(userId);
        Long associationId = user.getAssociationId();
        Association association = this.getById(associationId);
        if (!association.getPresidentUserId().equals(userId)){
            throw new ServiceException("您不是公会长，没有权限解散公会！");
        }
        userMapper.removeAssociationId(associationId);
        this.removeById(associationId);
        List<AssociationUser> userList = associationUserService.getUserList(associationId);
        associationUserService.removeBatchByIds(userList);
    }

    @Override
    public void createAssociation(CreateAssociationDTO dto) {
        LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(User::getAccount, dto.getPresidentAccount());
        User user = userMapper.selectOne(wrapper);

        Association association = new Association();
        association.setAvatar(dto.getAvatar());
        association.setCommissionRatio(BigDecimal.valueOf(0));
        association.setIntro(dto.getIntro());
        association.setName(dto.getName());
        association.setPresidentUserId(user.getId());
        association.setLevel(1);
        this.save(association);

        user.setAssociationId(association.getId());
        userMapper.updateById(user);
        associationUserService.signing(user.getId(),association.getId(),6,BigDecimal.ZERO);
        associationUserService.approval(association.getId(),user.getId(),Status.SUCCESS.getValue());
    }

    @Override
    public Page<Association> getAssociationPage(Integer page,Integer size) {
        LambdaQueryWrapper<Association> wrapper = Wrappers.lambdaQuery();
        wrapper.orderByDesc(Association::getLevel,Association::getCreateTime);

        Page<Association> associationPage = new Page<>(page, size);
        Page<Association> result = this.page(associationPage, wrapper);
        for (Association record : result.getRecords()) {

            User user = userMapper.selectById(record.getPresidentUserId());
            record.setPresidentAccount(user.getAccount());
            String partyIds = record.getPartyIds();
            if (StringUtils.isNotEmpty(partyIds)){
                List<String> list = Arrays.asList(partyIds.split(","));
                Double partyBill = userBillService.getPartyBill(list);
                record.setTotalNumber(partyBill);
            }
        }

        return result;
    }

    @Override
    public void deleteById(Long id) {
        userMapper.removeAssociationId(id);
        this.removeById(id);
        List<AssociationUser> userList = associationUserService.getUserList(id);
        associationUserService.removeBatchByIds(userList);
    }

    @Override
    public void updateOwner(Long associationId, String account) {
        LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(User::getAccount, account);
        User user = userMapper.selectOne(wrapper);

        AssociationUser userSign = associationUserService.getUserSign(user.getId());
        if (!user.getAssociationId().equals(associationId) || userSign == null){
            throw new ServiceException("用户不属于该公会");
        }
        Association association = this.getById(associationId);
        association.setPresidentUserId(user.getId());
        this.updateById(association);
    }

}
